While reading The Hacker Playbook 3, one of the first steps you’ll need to do is to install Powershell Empire. I ran into problems with dependencies between the current version in Git, and the version of Python included with Ubuntu 16.04. Rather than thrash about in dependency hell, I decided I’d opt to use Docker. Using Docker gives you quite a few advantages, some of which are:
- Easy updates
- No dependency problems
- Run multiple instances off the same config
There weren’t too many tutorials out there, so I decided to turn my notes into a blog post in hope that helps others.
Step 0: Do all-the-things as root
For the sake of saving me the time of making sure I preface everything with sudo
, we’re just going to elevate our shell to root. Once you get things wrapped up, the most secure way to do things would be to give your normal user access to docker, or just preface your docker commands with sudo. For now though,
sudo -i
Step 1: Install Docker
There’s not a lot to this one, just:
apt install docker.io jq
We install jq
as well so that we can parse json on the command line for some handy one-liners later in the post.
Step 2: Pull or Build the Image
You can opt to build your own image from the Empire source code, but that’s outside of the scope of this post. Instead, we’ll pull a copy from the global registry:
docker pull empireproject/empire
Step 3: Create a Volume
Now, we’re going to create a docker volume to store the configuration of Empire. If you don’t do this, every time you create a new container, you’ll have to redo the configuration steps. By creating a volume, you are separating the data used by the container from the container itself, allowing it to persist no matter what happens to the container(s) you build. For more on volumes, consult the official Docker docs on them
docker volume create empire-data
You can also create a symlink to the volume in a more handy place, like /opt/
. The following will do just that:
mkdir -p /opt/Empire/ && ln -s $(docker volume inspect empire-data \
| jq -r .[0].Mountpoint) /opt/Empire/data
Step 4: Create a Container from the Image
Now, we’re going to create our first container from the image. Run this as root:
docker run -it --name empire -v empire-data:/opt/Empire/data \
-p 443:443 --entrypoint bash empireproject/empire
This command does the following:
- Creates a container named ‘empire’
- It mounts the volume named ‘empire-data’ (created in step 3 above) to the directory
/opt/Empire/data
inside the container. - It binds port 443 (HTTPS) on our host to port 443 on the container. This is essentially a “port forward”.
- It sets the entrypoint to be
bash
. This means that when we run the container, it will drop us into a bash shell rather than an Empire shell. I found there was a need to run the various scripts and otherwise interact with the container outside the Empire shell and this makes it easy. If you omit theentrypoint
argument, you’ll be dropped straight into Empire’s interpreter.
At this point, you’re inside the container. Your current directory is /opt/Empire
, to run Empire, just run ./empire
to get into the interpreter. When you’re finished, exit
the Empire interpreter, and then type exit
one more time to exit the container. Note that unlike virtual machines, your container stops running the instant you exit it.
To start the container back up again, you can run:
docker start -ai empire
Summary
At this point, you have a single container named ‘empire’ that you can use for all of your C2 needs. Note that if you want to check out an upgraded version, you can just pull down the new image, and run a new container with a different name (e.g. empire-new) to test with. You can create separate volumes to manage separate data sets as well.